﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;

namespace RoketPack
{
    /// <summary>
    /// This basic downloader class provides an easy way to download data from URLs
    /// without having to set up a WebClient for each download.
    /// </summary>
    class Downloader
    {
        public Downloader()
        {
        }

        public static byte[] Grab(string url)
        {
            return new WebClient().DownloadData(new Uri(url).ToString());
        }

        public static byte[] Grab(string url, Manager.VoidLambdaDouble progressevent)
        {
            bool complete = false;
            bool thrown = false;
            Exception exception = null;
            byte[] data = null;
            WebClient wc = new WebClient();
            Object lockable = new Object();
            wc.DownloadDataCompleted += (sender, e) =>
                {
                    lock (lockable)
                    {
                        try
                        {
                            data = e.Result;
                            complete = true;
                        }
                        catch (System.Reflection.TargetInvocationException ex)
                        {
                            // Propagate the WebException instead of the
                            // TargetInvocationException.
                            exception = ex.InnerException;
                            thrown = true;
                        }
                    }
                };
            wc.DownloadProgressChanged += (sender, e) =>
                {
                    try
                    {
                        progressevent(e.ProgressPercentage);
                    }
                    catch (Exception ex)
                    {
                        lock (lockable)
                        {
                            exception = ex;
                            thrown = true;
                        }
                    }
                };
            wc.DownloadDataAsync(new Uri(url));

            while (!complete && !thrown)
            {
                Thread.Sleep(new TimeSpan(1));
            }

            lock (lockable)
            {
                // Propogate the exception across threading boundaries
                // in case any of the lambdas threw an exception.
                if (thrown)
                {
                    throw exception;
                }

                return data;
            }
        }

        public void Grab(string url, DownloadProgressChangedEventHandler onprogress, DownloadDataCompletedEventHandler oncomplete)
        {
            WebClient wc = new WebClient();
            wc.DownloadDataCompleted += oncomplete;
            wc.DownloadProgressChanged += onprogress;
            wc.DownloadDataAsync(new Uri(url));
        }
    }
}
